{% extends 'base.html' %}

{% block title %}非法账号识别 - 区块链交易行为特征分析与可视化系统{% endblock %}

{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
    <h1 class="h2"><i class="fas fa-shield-alt me-2"></i>非法账号识别</h1>
</div>

<!-- 修改分析表单部分 -->
<div class="card mb-4">
    <div class="card-header bg-primary text-white">
        <h5 class="mb-0"><i class="fas fa-search me-2"></i>地址分析</h5>
    </div>
    <div class="card-body">
        <form id="address-form">
            <div class="mb-3">
                <label for="address" class="form-label">以太坊地址</label>
                <div class="input-group">
                    <span class="input-group-text"><i class="fas fa-address-card"></i></span>
                    <input type="text" class="form-control" id="address" name="address" placeholder="输入要分析的区块链地址（例如: 0x16f2...）" required>
                </div>
                <div class="form-text">系统将查询与该地址相关的最近100条交易记录进行分析</div>
            </div>
            
            <!-- 增加模型选择下拉菜单 -->
            <div class="mb-3">
                <label for="model-select" class="form-label">选择分析模型</label>
                <div class="input-group">
                    <span class="input-group-text"><i class="fas fa-brain"></i></span>
                    <select class="form-select" id="model-select" name="model">
                        <option value="RandomForest">随机森林 (RandomForest)</option>
                        <option value="XGBoost" selected>XGBoost</option>
                        <option value="PDTGA">PDTGA</option>
                        <option value="GAT">图注意力网络 (GAT)</option>
                        <option value="MLP">深度神经网络 (MLP)</option>
                    </select>
                </div>
                <div class="form-text">选择用于风险分析的模型，不同模型有不同的性能特点</div>
            </div>
            
            <div class="d-grid gap-2">
                <button type="submit" class="btn btn-primary">
                    <i class="fas fa-search me-2"></i>开始分析
                </button>
            </div>
        </form>
    </div>
</div>

<!-- 加载提示 -->
<div id="loading" class="text-center py-5" style="display: none;">
    <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">分析中...</span>
    </div>
    <p class="mt-2">正在分析交易数据，请稍候...</p>
</div>

<!-- 分析结果 -->
<div id="results-container" style="display: none;">
    <!-- 结果摘要 -->
    <div class="card mb-4">
        <div class="card-header bg-success text-white">
            <h5 class="mb-0"><i class="fas fa-chart-pie me-2"></i>分析结果摘要</h5>
        </div>
        <div class="card-body">
            <div class="row">
                <div class="col-md-6">
                    <div class="chart-container" style="position: relative; height: 250px;">
                        <canvas id="resultsPieChart"></canvas>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="alert alert-info">
                        <h5><i class="fas fa-info-circle me-2"></i>分析说明</h5>
                        <p>系统基于深度学习模型分析交易行为特征，计算每个地址的风险概率。风险概率大于0.5的地址被视为可能存在风险的账号。</p>
                        <p>本分析仅供参考，不应作为唯一判断依据。</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <!-- 新增：模型性能卡片 -->
    <div class="card mb-4">
        <div class="card-header bg-info text-white">
            <h5 class="mb-0"><i class="fas fa-chart-line me-2"></i>模型性能</h5>
        </div>
        <div class="card-body">
            <div class="row">
                <div class="col-md-6">
                    <h5 id="model-name-display">模型: XGBoost</h5>
                    <div class="table-responsive">
                        <table class="table table-striped">
                            <thead>
                                <tr>
                                    <th>指标</th>
                                    <th>数值</th>
                                </tr>
                            </thead>
                            <tbody id="model-performance-body">
                                <!-- 模型性能数据将通过JavaScript动态添加 -->
                            </tbody>
                        </table>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="chart-container" style="position: relative; height: 200px;">
                        <canvas id="modelPerformanceChart"></canvas>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 详细结果表格 -->
    <div class="card mb-4">
        <div class="card-header bg-primary text-white">
            <h5 class="mb-0"><i class="fas fa-table me-2"></i>详细分析结果</h5>
        </div>
        <div class="card-body">
            <div class="table-responsive">
                <table class="table table-hover table-striped" id="results-table">
                    <thead>
                        <tr>
                            <th>地址</th>
                            <th>风险概率</th>
                            <th>状态</th>
                            <th>风险等级</th>
                        </tr>
                    </thead>
                    <tbody id="results-body">
                        <!-- 结果将通过JavaScript动态添加 -->
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- 相关交易 -->
    <div class="card mb-4">
        <div class="card-header bg-info text-white">
            <h5 class="mb-0"><i class="fas fa-exchange-alt me-2"></i>相关交易</h5>
        </div>
        <div class="card-body">
            <div class="table-responsive">
                <table class="table table-hover table-striped" id="transactions-table">
                    <thead>
                        <tr>
                            <th>交易哈希</th>
                            <th>区块高度</th>
                            <th>时间</th>
                            <th>发送方</th>
                            <th>接收方</th>
                            <th>金额</th>
                        </tr>
                    </thead>
                    <tbody id="transactions-body">
                        <!-- 交易将通过JavaScript动态添加 -->
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<!-- 错误提示 -->
<div id="error-message" class="alert alert-danger" style="display: none;">
    <i class="fas fa-exclamation-triangle me-2"></i>
    <span id="error-text">分析时发生错误</span>
</div>
{% endblock %}

{% block extra_js %}
{{ super() }}
<script>
    document.addEventListener('DOMContentLoaded', function() {
        console.log("页面已加载");
        const addressForm = document.getElementById('address-form');
        const loadingDiv = document.getElementById('loading');
        const resultsContainer = document.getElementById('results-container');
        const errorMessage = document.getElementById('error-message');
        const errorText = document.getElementById('error-text');
        
        // 模型性能图表变量
        let modelPerformanceChart = null;
        
        // 地址查询表单提交处理
        addressForm.addEventListener('submit', function(e) {
            console.log("表单提交");
            // 阻止表单默认提交行为
            e.preventDefault();
            
            // 获取用户输入的地址和选择的模型
            const address = document.getElementById('address').value.trim();
            const model = document.getElementById('model-select').value;
            console.log("查询地址:", address, "选择模型:", model);
            
            // 验证必填字段
            if (!address) {
                errorText.textContent = '请输入要分析的区块链地址';
                errorMessage.style.display = 'block';
                return;
            }
            
            // 显示加载提示，隐藏其他内容
            loadingDiv.style.display = 'block';
            resultsContainer.style.display = 'none';
            errorMessage.style.display = 'none';
            
            // 发送分析请求
            fetch('/api/fraud_detection/analyze', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ 
                    address: address,
                    model_type: model 
                })
            })
            .then(response => {
                console.log("收到响应:", response.status);
                if (!response.ok) {
                    throw new Error('网络响应异常: ' + response.status);
                }
                return response.json();
            })
            .then(data => {
                console.log("响应数据:", data);
                // 隐藏加载提示
                loadingDiv.style.display = 'none';
                
                // 处理结果
                if (data.error) {
                    // 显示错误信息
                    errorText.textContent = data.error;
                    errorMessage.style.display = 'block';
                } else {
                    // 显示结果容器
                    resultsContainer.style.display = 'block';

                    // 如果有消息，显示消息
                    if (data.message) {
                        errorText.textContent = data.message;
                        errorMessage.style.display = 'block';
                        errorMessage.className = 'alert alert-warning'; // 使用警告样式而非错误样式
                    } else {
                        errorMessage.style.display = 'none';
                    }
                    
                    // 渲染结果
                    renderResults(data.results);
                    renderTransactions(data.transactions);
                    renderModelPerformance(data.model_performance, data.model_name);
                }
            })
            .catch(error => {
                console.error("请求错误:", error);
                // 显示错误信息
                loadingDiv.style.display = 'none';
                errorText.textContent = '分析时发生错误: ' + error.message;
                errorMessage.style.display = 'block';
            });
        });
        
        // 渲染模型性能数据
        function renderModelPerformance(performance, modelName) {
            console.log("渲染模型性能:", performance, modelName);
            
            // 更新模型名称显示
            document.getElementById('model-name-display').textContent = `模型: ${modelName}`;
            
            // 更新性能指标表格
            const performanceBody = document.getElementById('model-performance-body');
            performanceBody.innerHTML = '';
            
            // 添加性能指标行
            const metrics = [
                { key: 'accuracy', name: '准确率 (Accuracy)' },
                { key: 'precision', name: '精确率 (Precision)' },
                { key: 'recall', name: '召回率 (Recall)' },
                { key: 'f1_score', name: 'F1分数 (F1-Score)' }
            ];
            
            metrics.forEach(metric => {
                const row = document.createElement('tr');
                const value = performance[metric.key];
                row.innerHTML = `
                    <td>${metric.name}</td>
                    <td>${(value * 100).toFixed(2)}%</td>
                `;
                performanceBody.appendChild(row);
            });
            
            // 渲染性能指标图表
            renderPerformanceChart(performance, modelName);
        }
        
        // 渲染性能指标图表
        function renderPerformanceChart(performance, modelName) {
            const ctx = document.getElementById('modelPerformanceChart').getContext('2d');
            
            // 销毁现有图表（如果存在）
            if (modelPerformanceChart) {
                modelPerformanceChart.destroy();
            }
            
            const metrics = ['准确率', '精确率', '召回率', 'F1分数'];
            const values = [
                performance.accuracy * 100,
                performance.precision * 100,
                performance.recall * 100,
                performance.f1_score * 100
            ];
            
            // 创建新图表
            modelPerformanceChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: metrics,
                    datasets: [{
                        label: `${modelName} 模型性能`,
                        data: values,
                        backgroundColor: [
                            'rgba(54, 162, 235, 0.7)',
                            'rgba(75, 192, 192, 0.7)',
                            'rgba(255, 206, 86, 0.7)',
                            'rgba(153, 102, 255, 0.7)'
                        ],
                        borderColor: [
                            'rgba(54, 162, 235, 1)',
                            'rgba(75, 192, 192, 1)',
                            'rgba(255, 206, 86, 1)',
                            'rgba(153, 102, 255, 1)'
                        ],
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true,
                            max: 100,
                            ticks: {
                                callback: function(value) {
                                    return value + '%';
                                }
                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return context.dataset.label + ': ' + context.parsed.y.toFixed(2) + '%';
                                }
                            }
                        }
                    }
                }
            });
        }
        
        // 渲染分析结果
        function renderResults(results) {
            console.log("渲染结果:", results);
            // 清空结果表格
            const resultsBody = document.getElementById('results-body');
            resultsBody.innerHTML = '';
            
            // 计算合法和非法账号数量
            let fraudulentCount = 0;
            let legitimateCount = 0;
            let noDataCount = 0;
            
            // 添加结果行
            results.forEach(result => {
                const row = document.createElement('tr');
                
                // 检查是否有数据
                if (result.status === 'No Data') {
                    row.classList.add('table-secondary');
                    noDataCount++;
                    
                    // 设置单元格内容 - 无数据情况
                    row.innerHTML = `
                        <td title="${result.address}">${result.address.substring(0, 10)}...</td>
                        <td>N/A</td>
                        <td>无数据</td>
                        <td><span class="badge bg-secondary">无法评估</span></td>
                    `;
                    
                    resultsBody.appendChild(row);
                    return; // 跳过后续处理
                }
                
                // 设置行的背景色
                if (result.probability > 0.7) {
                    row.classList.add('table-danger');
                } else if (result.probability > 0.5) {
                    row.classList.add('table-warning');
                } else {
                    row.classList.add('table-success');
                }
                
                // 计数
                if (result.probability > 0.5) {
                    fraudulentCount++;
                } else {
                    legitimateCount++;
                }
                
                // 风险等级
                let riskLevel;
                if (result.probability > 0.7) {
                    riskLevel = '<span class="badge bg-danger">高风险</span>';
                } else if (result.probability > 0.5) {
                    riskLevel = '<span class="badge bg-warning text-dark">中风险</span>';
                } else if (result.probability > 0.3) {
                    riskLevel = '<span class="badge bg-info text-dark">低风险</span>';
                } else {
                    riskLevel = '<span class="badge bg-success">安全</span>';
                }
                
                // 设置单元格内容
                row.innerHTML = `
                    <td title="${result.address}">${result.address.substring(0, 10)}...</td>
                    <td>${(result.probability * 100).toFixed(2)}%</td>
                    <td>${result.status}</td>
                    <td>${riskLevel}</td>
                `;
                
                resultsBody.appendChild(row);
            });
            
            // 渲染饼图
            renderPieChart(legitimateCount, fraudulentCount, noDataCount);
        }
        
        // 渲染交易列表
        function renderTransactions(transactions) {
            console.log("渲染交易:", transactions);
            // 清空交易表格
            const transactionsBody = document.getElementById('transactions-body');
            transactionsBody.innerHTML = '';
            
            // 检查是否有交易数据
            if (!transactions || transactions.length === 0) {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td colspan="6" class="text-center text-muted">
                        <i class="fas fa-info-circle me-2"></i>没有找到相关交易记录
                    </td>
                `;
                transactionsBody.appendChild(row);
                return;
            }
            
            // 添加交易行
            transactions.forEach(tx => {
                const row = document.createElement('tr');
                
                // 格式化时间戳
                const date = new Date(tx.TimeStamp * 1000);
                const formattedDate = date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
                
                // 设置单元格内容
                row.innerHTML = `
                    <td title="${tx.TxHash}">${tx.TxHash.substring(0, 10)}...</td>
                    <td>${tx.BlockHeight}</td>
                    <td>${formattedDate}</td>
                    <td title="${tx.From}">${tx.From.substring(0, 10)}...</td>
                    <td title="${tx.To}">${tx.To.substring(0, 10)}...</td>
                    <td>${tx.Value}</td>
                `;
                
                transactionsBody.appendChild(row);
            });
        }
        
        // 渲染饼图
        function renderPieChart(legitimateCount, fraudulentCount, noDataCount) {
            console.log("渲染饼图:", legitimateCount, fraudulentCount, noDataCount);
            const ctx = document.getElementById('resultsPieChart').getContext('2d');
            
            // 销毁现有图表（如果存在）
            if (window.resultChart) {
                window.resultChart.destroy();
            }
            
            // 准备图表数据
            let labels = [];
            let data = [];
            let backgroundColor = [];
            let borderColor = [];
            
            // 根据情况添加数据
            if (legitimateCount > 0) {
                labels.push('合法账号');
                data.push(legitimateCount);
                backgroundColor.push('rgba(40, 167, 69, 0.7)');
                borderColor.push('rgba(40, 167, 69, 1)');
            }
            
            if (fraudulentCount > 0) {
                labels.push('可疑账号');
                data.push(fraudulentCount);
                backgroundColor.push('rgba(220, 53, 69, 0.7)');
                borderColor.push('rgba(220, 53, 69, 1)');
            }
            
            if (noDataCount > 0) {
                labels.push('无数据');
                data.push(noDataCount);
                backgroundColor.push('rgba(108, 117, 125, 0.7)');
                borderColor.push('rgba(108, 117, 125, 1)');
            }
            
            // 如果没有数据，添加默认显示
            if (labels.length === 0) {
                labels = ['无数据'];
                data = [1];
                backgroundColor = ['rgba(108, 117, 125, 0.7)'];
                borderColor = ['rgba(108, 117, 125, 1)'];
            }
            
            // 创建新图表
            window.resultChart = new Chart(ctx, {
                type: 'pie',
                data: {
                    labels: labels,
                    datasets: [{
                        data: data,
                        backgroundColor: backgroundColor,
                        borderColor: borderColor,
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        title: {
                            display: true,
                            text: '账号风险分布'
                        },
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    const label = context.label || '';
                                    const value = context.raw || 0;
                                    const total = context.dataset.data.reduce((a, b) => a + b, 0);
                                    const percentage = ((value / total) * 100).toFixed(2);
                                    return `${label}: ${value} 个 (${percentage}%)`;
                                }
                            }
                        }
                    }
                }
            });
        }
    });
</script>
{% endblock %}